﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Operations.cs" company="dimamartovoi">
//   Apache License
//   Version 2.0, January 2004
//   http://www.apache.org/licenses
// </copyright>
// <summary>
//   The operations.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Globalization;

namespace ActorModel.Evolution.Operations
{
    /// <summary>
    ///     The operations.
    /// </summary>
    public static class Operations
    {
        #region Public Methods and Operators

        /// <summary>
        /// The and.
        /// </summary>
        /// <param name="first">
        /// The first.
        /// </param>
        /// <param name="second">
        /// The second.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool And(bool first, bool second)
        {
            return first && second;
        }

        /// <summary>
        /// The and.
        /// </summary>
        /// <param name="first">
        /// The first.
        /// </param>
        /// <param name="second">
        /// The second.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string And(string first, string second)
        {
            return Intersect(first, second);
        }

        /// <summary>
        /// The as number.
        /// </summary>
        /// <param name="s">
        /// The s.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int AsNumber(string s)
        {
            return string.IsNullOrEmpty(s) ? 0 : Convert.ToInt32(s, 2);
        }

        /// <summary>
        /// The as number.
        /// </summary>
        /// <param name="s">
        /// The s.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int AsNumber(bool s)
        {
            return s ? 1 : 0;
        }

        /// <summary>
        /// The as string.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string AsString(int i)
        {
            return Convert.ToString(i, 2);
        }

        /// <summary>
        /// The as string.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string AsString(bool i)
        {
            return i ? 1.ToString(CultureInfo.InvariantCulture) : 0.ToString(CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// The devide.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Devide(int i, int j)
        {
            return i / j;
        }

        /// <summary>
        /// The equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool Equals(int i, int j)
        {
            return i == j;
        }

        /// <summary>
        /// The equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool Equals(string i, string j)
        {
            return i == j;
        }

        /// <summary>
        /// The equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool Equals(bool i, bool j)
        {
            return i == j;
        }

        /// <summary>
        /// The get lenth.
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int GetLenth(string source)
        {
            return source.Length;
        }

        /// <summary>
        /// The intersect.
        /// </summary>
        /// <param name="one">
        /// The one.
        /// </param>
        /// <param name="another">
        /// The another.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string Intersect(string one, string another)
        {
            var intersect = new char[Math.Min(one.Length, another.Length)];
            for (int i = 0; i < intersect.Length; i++)
            {
                if (one[i] == '1' && another[i] == '1')
                {
                    intersect[i] = '1';
                }
                else
                {
                    intersect[i] = '0';
                }
            }

            return new string(intersect);
        }

        /// <summary>
        /// The inverse.
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string Inverse(string source)
        {
            var result = new char[source.Length];
            for (int i = 0; i < source.Length; i++)
            {
                result[i] = source[source.Length - i - 1];
            }

            return new string(result);
        }

        /// <summary>
        /// The is substring.
        /// </summary>
        /// <param name="target">
        /// The target.
        /// </param>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool IsSubstring(string target, string source)
        {
            return source.Contains(target);
        }

        /// <summary>
        /// The less.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool Less(int i, int j)
        {
            return i < j;
        }

        /// <summary>
        /// The less.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool Less(string i, string j)
        {
            int res = string.CompareOrdinal(i, j);
            if (res < 0)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// The less or equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool LessOrEquals(int i, int j)
        {
            return i <= j;
        }

        /// <summary>
        /// The less or equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool LessOrEquals(string i, string j)
        {
            return Less(i, j) || i == j;
        }

        /// <summary>
        /// The max.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Max(int i, int j)
        {
            return Math.Max(i, j);
        }

        /// <summary>
        /// The min.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Min(int i, int j)
        {
            return Math.Min(i, j);
        }

        /// <summary>
        /// The minus.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Minus(int i, int j)
        {
            return i - j;
        }

        /// <summary>
        /// The modulo.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Modulo(int i, int j)
        {
            return i % j;
        }

        /// <summary>
        /// The more.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool More(int i, int j)
        {
            return i > j;
        }

        /// <summary>
        /// The more.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool More(string i, string j)
        {
            int res = string.CompareOrdinal(i, j);
            if (res > 0)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// The more or equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool MoreOrEquals(int i, int j)
        {
            return i >= j;
        }

        /// <summary>
        /// The more or equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool MoreOrEquals(string i, string j)
        {
            return More(i, j) || i == j;
        }

        /// <summary>
        /// The multiply.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Multiply(int i, int j)
        {
            return i * j;
        }

        /// <summary>
        /// The not.
        /// </summary>
        /// <param name="first">
        /// The first.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool Not(bool first)
        {
            return !first;
        }

        /// <summary>
        /// The not.
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string Not(string source)
        {
            var result = new char[source.Length];
            for (int i = 0; i < source.Length; i++)
            {
                if (source[i] == '1')
                {
                    result[i] = '0';
                }
                else
                {
                    result[i] = '1';
                }
            }

            return new string(result);
        }

        /// <summary>
        /// The not equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool NotEquals(int i, int j)
        {
            return i != j;
        }

        /// <summary>
        /// The not equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool NotEquals(string i, string j)
        {
            return i != j;
        }

        /// <summary>
        /// The not equals.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool NotEquals(bool i, bool j)
        {
            return i != j;
        }

        /// <summary>
        /// The or.
        /// </summary>
        /// <param name="first">
        /// The first.
        /// </param>
        /// <param name="second">
        /// The second.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool Or(bool first, bool second)
        {
            return first || second;
        }

        /// <summary>
        /// The or.
        /// </summary>
        /// <param name="first">
        /// The first.
        /// </param>
        /// <param name="second">
        /// The second.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string Or(string first, string second)
        {
            return Union(first, second);
        }

        /// <summary>
        /// The plus.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Plus(int i, int j)
        {
            return i + j;
        }

        /// <summary>
        /// The plus.
        /// </summary>
        /// <param name="i">
        /// The i.
        /// </param>
        /// <param name="j">
        /// The j.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string Plus(string i, string j)
        {
            return i + j;
        }

        /// <summary>
        /// The replace substring.
        /// </summary>
        /// <param name="from">
        /// The from.
        /// </param>
        /// <param name="to">
        /// The to.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string ReplaceSubstring(int from, int to, string value, string source)
        {
            char[] result;
            if (string.IsNullOrEmpty(source))
            {
                result = new char[to + 1];
                for (int i = 0; i < result.Length; i++)
                {
                    result[i] = '0';
                }

                return ReplaceSubstring(from, to, value, new string(result));
            }

            result = new char[source.Length];
            for (int i = 0; i < result.Length; i++)
            {
                if (i >= from && i <= to)
                {
                    result[i] = value[i - from];
                    continue;
                }

                result[i] = source[i];
            }

            return new string(result);
        }

        /// <summary>
        /// The substring.
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <param name="from">
        /// The from.
        /// </param>
        /// <param name="to">
        /// The to.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string Substring(string source, int from, int to)
        {
            return source.Substring(from, to - from + 1);
        }

        /// <summary>
        /// The union.
        /// </summary>
        /// <param name="one">
        /// The one.
        /// </param>
        /// <param name="another">
        /// The another.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string Union(string one, string another)
        {
            var offset = new char[Math.Abs(one.Length - another.Length)];
            if (one.Length > another.Length)
            {
                for (int i = 0; i < one.Length - another.Length; i++)
                {
                    offset[i] = one[another.Length + i];
                }
            }

            if (another.Length > one.Length)
            {
                for (int i = 0; i < another.Length - one.Length; i++)
                {
                    offset[i] = another[one.Length + i];
                }
            }

            var union = new char[Math.Min(one.Length, another.Length)];
            for (int i = 0; i < union.Length; i++)
            {
                if (one[i] == '0' && another[i] == '0')
                {
                    union[i] = '0';
                }
                else
                {
                    union[i] = '1';
                }
            }

            var unionStr = new string(union);
            var offsetStr = new string(offset);
            return unionStr + offsetStr;
        }

        /// <summary>
        /// The xor.
        /// </summary>
        /// <param name="one">
        /// The one.
        /// </param>
        /// <param name="another">
        /// The another.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string Xor(string one, string another)
        {
            var xor = new char[Math.Min(one.Length, another.Length)];
            for (int i = 0; i < xor.Length; i++)
            {
                if (one[i] != another[i])
                {
                    xor[i] = '1';
                }
                else
                {
                    xor[i] = '0';
                }
            }

            return new string(xor);
        }

        #endregion
    }
}